Assembling the source data for a hazard and vulnerability mapping tool for South Gloucestershire¶

James Thomas, Josh Howkins
April 2023

For demonstration purposes only.

To demonstrate how an overall risk analysis might proceed, LSOA scores for vulnerability and for exposure (from the hazard analysis) were split into tertiles and plotted onto a 3x3 risk matrix for visualisation. Vulnerability and heat exposure risk matrix score was mapped for a "heat vulnerability" layer, and vulnerability and flooding risk matrix score for a "flooding vulnerability" layer.

In [1]:
import geopandas as gpd
import pandas as pd

import utils

%matplotlib inline
utils.set_plotting_defaults()

Combining hazard and vulnerability¶

In [2]:
heat_average_daily_maximum = gpd.read_file('../../hazard/data/output/heat/heat_averages.geojson')[['LSOA21CD', 'average_daily_maximum']]
heat_average_daily_maximum = heat_average_daily_maximum.set_axis(['lsoa21cd', 'average_daily_maximum'], axis='columns')
heat_average_daily_maximum = heat_average_daily_maximum.set_index('lsoa21cd')
In [3]:
flooding_typical = gpd.read_file('../../hazard/data/output/flooding/typical/proportion_flooded.geojson')[['LSOA21CD', 'proportion_footprints_flooded']]
flooding_typical = flooding_typical.set_axis(['lsoa21cd', 'proportion_footprints_flooded_typical'], axis='columns')
flooding_typical = flooding_typical.set_index('lsoa21cd')
In [4]:
flooding_disaster = gpd.read_file('../../hazard/data/output/flooding/disaster/proportion_flooded.geojson')[['LSOA21CD', 'proportion_footprints_flooded']]
flooding_disaster = flooding_disaster.set_axis(['lsoa21cd', 'proportion_footprints_flooded_disaster'], axis='columns')
flooding_disaster = flooding_disaster.set_index('lsoa21cd')
In [5]:
vulnerability_score = gpd.read_file('../data/06_index/index.geojson')[['lsoa21cd', 'score', 'lsoa21nm', 'geometry']]
vulnerability_score = vulnerability_score.set_axis(['lsoa21cd', 'vulnerability_score', 'lsoa21nm', 'geometry'], axis='columns')
vulnerability_score = vulnerability_score.set_index('lsoa21cd')
In [6]:
data = gpd.GeoDataFrame(pd.concat(
    [
        heat_average_daily_maximum,
        flooding_typical,
        flooding_disaster,
        vulnerability_score,
    ],
    axis='columns'
))

data.head()
Out[6]:
average_daily_maximum proportion_footprints_flooded_typical proportion_footprints_flooded_disaster vulnerability_score lsoa21nm geometry
lsoa21cd
E01014861 21.427320 0.005091 0.030545 80.658393 South Gloucestershire 005A POLYGON ((360201.381 185694.381, 361157.149 18...
E01014862 21.311926 0.000000 0.005450 46.709951 South Gloucestershire 005B POLYGON ((363718.594 185287.703, 363954.500 18...
E01014863 21.095795 0.000000 0.000000 163.648737 South Gloucestershire 004A POLYGON ((363143.202 188406.407, 363165.150 18...
E01014864 21.210447 0.000000 0.000000 138.518660 South Gloucestershire 004B POLYGON ((365050.094 188519.500, 365133.501 18...
E01014865 21.856823 0.031250 0.061458 76.495958 South Gloucestershire 024A POLYGON ((370769.406 171271.906, 370914.303 17...

An example of a high/medium/low indicator¶

For vulnerability and heat, the score or indicator is simply divided into three tertiles:

  • Lowest tertile → Low,
  • Middle tertile → Medium,
  • Highest tertile → High.

For flooding, LSOAs are graded:

  • No buildings flooded in either a typical (1 in 100 year) or a disaster (1 in 1000 year) event → Low,
  • Buildings flooded in a disaster (1 in 1000 year) but not in a typical (1 in 100 year) event → Medium,
  • Buildings flooded in both a typical (1 in 100 year) and disaster (1 in 1000 year) event → High.

(For demonstration purposes, there is no grading no number of properties flooded.)

image.png

image.png

The individual axes¶

In [7]:
data['axis_vulnerability'] = 1 + pd.qcut(data['vulnerability_score'], 3, labels=False)
data['axis_heat'] = 1 + pd.qcut(data['average_daily_maximum'], 3, labels=False)
data['axis_flooding'] = 1 + (data['proportion_footprints_flooded_typical'] > 0) + (data['proportion_footprints_flooded_disaster'] > 0)
In [8]:
data.explore('axis_vulnerability', cmap='viridis', categorical=True)
Out[8]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [9]:
data.explore('axis_heat', cmap='viridis', categorical=True)
Out[9]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [10]:
data.explore('axis_flooding', cmap='viridis', categorical=True)
Out[10]:
Make this Notebook Trusted to load map: File -> Trust Notebook

The combined score¶

Add the axes to simulate H/M/L like a risk matrix.

In [11]:
data['combined_heat_vulnerability'] = data['axis_vulnerability'] + data['axis_heat']
data['combined_flooding_vulnerability'] = data['axis_vulnerability'] + data['axis_flooding']

data.drop(columns='geometry').to_csv('../data/07_overall/combined.csv', float_format='%0.3f')
data.to_file('../data/07_overall/combined.geojson', float_format='%0.3f')
In [12]:
m = data.explore('combined_heat_vulnerability', cmap='magma_r', categorical=True)
m.save('../data/07_overall/combined_heat_vulnerability.html')
m
Out[12]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [13]:
m = data.explore('combined_flooding_vulnerability', cmap='magma_r', categorical=True)
m.save('../data/07_overall/combined_flooding_vulnerability.html')
m
Out[13]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [ ]: